﻿using System;
using System.IO;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using System.Collections;

namespace CNVP.Framework.Utils
{
    /// <summary>
    /// 文件压缩类
    /// </summary>
    public static class ZipClass
    {
        #region "文件压缩函数"
        /*调用实例
         * string[] FileProperties = new string[2];
         * FileProperties[0] = Server.MapPath("~/JCms");
         * FileProperties[1] = Server.MapPath("~/JCms.rar");
         * try
         * {
         *     ZipClass.ZipFolder(FileProperties);
         * }
         * catch
         * {
         * }
         */
        private static void ZipFile(string FileToZip, string ZipedFile, int CompressionLevel, int BlockSize)
        {
            if (!System.IO.File.Exists(FileToZip))
            {
                throw new System.IO.FileNotFoundException("The specified file " + FileToZip + " could not be found. Zipping aborderd");
            }

            System.IO.FileStream StreamToZip = new System.IO.FileStream(FileToZip, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            System.IO.FileStream ZipFile = System.IO.File.Create(ZipedFile);
            ZipOutputStream ZipStream = new ZipOutputStream(ZipFile);
            ZipEntry ZipEntry = new ZipEntry("ZippedFile");
            ZipStream.PutNextEntry(ZipEntry);
            ZipStream.SetLevel(CompressionLevel);
            byte[] buffer = new byte[BlockSize];
            System.Int32 size = StreamToZip.Read(buffer, 0, buffer.Length);
            ZipStream.Write(buffer, 0, size);
            try
            {
                while (size < StreamToZip.Length)
                {
                    int sizeRead = StreamToZip.Read(buffer, 0, buffer.Length);
                    ZipStream.Write(buffer, 0, sizeRead);
                    size += sizeRead;
                }
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
            ZipStream.Finish();
            ZipStream.Close();
            StreamToZip.Close();
        }

        private static string AddZip(string fileName, string zipName, ZipOutputStream s)
        {
            Crc32 crc = new Crc32();
            try
            {
                FileStream fs = File.OpenRead(fileName);
                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                fileName = Path.GetFileName(fileName);
                long fileLength = fs.Length;
                fs.Close();

                ZipEntry entry = new ZipEntry(zipName);
                entry.DateTime = DateTime.Now;
                entry.Size = fileLength;

                crc.Reset();
                crc.Update(buffer);
                entry.Crc = crc.Value;
                s.PutNextEntry(entry);
                s.Write(buffer, 0, buffer.Length);

                return string.Empty;
            }
            catch (Exception addEx)
            {
                return addEx.ToString();
            }
        }

        private static void AddFolder(string folderName, string zipName, ZipOutputStream s)
        {
            if (Directory.Exists(folderName))
            {
                foreach (string str in Directory.GetFileSystemEntries(folderName))
                {
                    if (File.Exists(str))
                        AddZip(str, zipName + "\\" + str.Substring(str.LastIndexOf("\\") + 1), s);
                    else
                        AddFolder(str, zipName + "\\" + str.Substring(str.LastIndexOf("\\") + 1), s);
                }
            }
        }

        private static void AddTemplateFolder(string folderName, ZipOutputStream s)
        {
            if (Directory.Exists(folderName))
            {
                foreach (string str in Directory.GetFileSystemEntries(folderName))
                {
                    if (File.Exists(str))
                        AddZip(str, str.Substring(str.LastIndexOf("\\") + 1), s);
                    else
                        AddFolder(str, str.Substring(str.LastIndexOf("\\") + 1), s);
                }
            }
        }

        private static void CreateTemplateZip(string[] args)
        {
            string dirName = null;
            dirName = Path.GetDirectoryName(Path.GetFullPath(args[1]));
            if (!Directory.Exists(dirName))
            {
                Directory.CreateDirectory(dirName);
            }
            ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));

            s.SetLevel(6); // 0 - store only to 9 - means best compression

            AddTemplateFolder(args[0], s);

            s.Finish();
            s.Close();
        }
        /// <summary>
        /// 文件压缩类
        /// </summary>
        /// <param name="args">字符数组：压缩目录名称，压缩包名称
        /// <para>例如：</para>
        /// <para>string[] FileProperties = new string[2];</para>
        /// <para>FileProperties[0] = Server.MapPath("~/JCms");</para>
        /// <para>FileProperties[1] = Server.MapPath("~/JCms.rar");</para>
        /// </param>
        public static void ZipFolder(string[] args)
        {
            string dirName = null;
            dirName = Path.GetDirectoryName(Path.GetFullPath(args[1]));
            if (!Directory.Exists(dirName))
            {
                Directory.CreateDirectory(dirName);
            }
            ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));

            s.SetLevel(9); // 0 - store only to 9 - means best compression

            AddTemplateFolder(args[0], s);

            s.Finish();
            s.Close();
        }
        #endregion
        #region "文件解压缩函数"
        /*调用实例
         * string BasePath=Server.MapPath("~/Apollo");
         * if (!Directory.Exists(BasePath))
         * {
         *      Directory.CreateDirectory(BasePath);
         * }
         * using (FileStream fs = File.Open(Server.MapPath("~/JCms.rar"), FileMode.Open))
         * {
         *      ZipUtils.ExtractZip(fs, BasePath);
         * }
         *
         */
        /// <summary>
        /// 文件解压缩
        /// </summary>
        /// <param name="input">压缩包文件</param>
        /// <param name="target">解压缩目录</param>
        public static void ExtractZip(Stream input, string target)
        {
            using (ZipInputStream st = new ZipInputStream(input))
            {
                ZipEntry ze;
                byte[] buffer = new byte[0x1000];
                while ((ze = st.GetNextEntry()) != null)
                {
                    string filename = ze.Name;
                    string dir = Path.Combine(target, filename);
                    string path = Path.GetDirectoryName(Path.GetFullPath(dir));
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                    if (ze.IsFile)
                    {
                        using (FileStream ts = File.Create(dir))
                        {
                            int num = 0;
                            while ((num = st.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                if (num > 0)
                                {
                                    ts.Write(buffer, 0, num);
                                }
                            }
                            ts.Flush();
                            ts.Close();
                        }
                    }
                    else if (ze.IsDirectory)
                    {
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }
                    }
                }
            }
        }
        #endregion
    }
}